package com.sneaker.shower.socket.repository;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sneaker.shower.socket.Channel;
import com.sneaker.shower.socket.Group;
import com.sneaker.shower.socket.feature.DelegateSignAble;
import com.sneaker.shower.socket.feature.ListGroup;
import com.sneaker.shower.socket.feature.SignAble;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Optional;

/**
 * <h1>ChannelRepository</h1>
 * <pre>
 * @Description
 * </pre>
 *
 * @Author lopo
 * @Date 2018/10/19
 */
public class ChannelRepository extends ListRepository<Channel> {
    private static final Logger logger = LoggerFactory.getLogger(ChannelRepository.class);
    private static ObjectMapper objectMapper = new ObjectMapper();
    private transient GroupRepository<Channel> groupRepository;

    public ChannelRepository(GroupRepository<Channel> groupRepository) {
        this.groupRepository = groupRepository;
    }

    /**
     * 保存组时保存元素
     *
     * @param channel channel
     */
    @Override
    public Channel save(Channel channel) {
        super.save(channel);
        if (channel instanceof DelegateSignAble) {
            SignAble signAble = ((DelegateSignAble) channel).getSignAble();
            registerGroup(signAble, channel);
            return channel;
        }
        registerGroup(channel, channel);
        return channel;
    }

    private void registerGroup(SignAble signAble, Channel channel) {
        if (signAble instanceof Group) {
            Collection channels = ((Group) signAble).group();
            if (channels == null || channels.isEmpty()) {
                return;
            }
            channels.forEach((e) -> {
                ListGroup listGroup = new ListGroup((SignAble) e);
                listGroup.add(channel);
                channel.groups().add(groupRepository.save(listGroup));
            });
        }
    }

    /**
     * 删除组时保存元素
     *
     * @param sign
     */
    @Override
    public void delete(SignAble sign) {
        logger.info("~{}", new RuntimeException());
        logger.info("repository delete {}", sign.sign());
        Channel channel = super.get(sign);
        logger.info("repository query {}", Optional.ofNullable(channel).map(SignAble::sign));
        if (channel == null) {
            return;
        }
        Collection<Group<Channel>> groups = channel.groups();
        try {
            logger.info("group repository query {}", objectMapper.writeValueAsString(groups));
            if (groups != null && !groups.isEmpty()) {
                groups.forEach((e) -> e.remove(channel));
            }
            logger.info("group repository after {}", groupRepository.peek(null));
            super.delete(sign);
            logger.info("repository after {}", this.peek(null));
        } catch (Exception e) {
            logger.error("`", e);
        }
    }
}
